package com.heatup.apt.api.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.heatup.apt.api.controller.pay.util.PropertiesUtil;
import com.heatup.apt.api.service.CompanyStaffService;
import com.heatup.apt.api.service.CourseSignService;
import com.heatup.apt.api.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.heatup.apt.api.service.AccessService;
import com.heatup.apt.common.util.DesUtils;
import com.heatup.apt.common.util.JsonClient;
import com.heatup.apt.common.util.JsonTools;
import com.heatup.apt.common.util.RequestTools;
import com.heatup.apt.common.util.ResponseTools;
import com.heatup.apt.common.util.StringUtil;
import com.heatup.apt.model.api.ApiResultModel;
import com.heatup.apt.model.user.UserInfo;

/**
 * 微信分享跳转控制器
 * 
 * @author jixiangyun 2016年10月25日 下午6:07:06
 */
@RequestMapping(value = "/redirect")
@Controller
public class WeiXinShareController extends BaseController{
	
	//APPID
	public static final String APP_ID = String.valueOf(PropertiesUtil.get("wechat_appid")).trim(); //"wx65db45e85c1be9c4";
	//APP_scret
	public static final String APP_SECRET =String.valueOf(PropertiesUtil.get("wechat_secret")).trim(); //"3816ac8f220a3e9150fbab7321064d45";
	//填写为authorization_code
	public static final String GRANT_TYPE = "authorization_code";
	//获取access_token
	public static final String GET_ACCESS_TOKEN =String.valueOf(PropertiesUtil.get("wechat_oaut2_url")).trim(); //"https://api.weixin.qq.com/sns/oauth2/access_token";
	//刷新 access_token
	public static final String REFLASH_DATA = String.valueOf(PropertiesUtil.get("wechat_refreshtoken_url")).trim();// "https://api.weixin.qq.com/sns/oauth2/refresh_token";
	//获取用户基础信息
	public static final String GET_USER_INFO = String.valueOf(PropertiesUtil.get("wechat_sns_userinfo_url")).trim();//"https://api.weixin.qq.com/sns/userinfo";
	
	public static final String BASE_URL =String.valueOf(PropertiesUtil.get("wechat_base_url"));//"http://h5.sincebest.com/#!";
	
	public static final String TEACHER_URL = String.valueOf(PropertiesUtil.get("wechat_teacher_url"));

	public static final String DES_KEY = String.valueOf(PropertiesUtil.get("des_key")).trim();
	//获取微信语言
	public static final String LANG = "zh_CN";
	//log
	private static final Logger logger = LoggerFactory.getLogger(WeiXinShareController.class);
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private AccessService accessService;

	@Autowired
    CourseSignService courseSignService;
	
	@Autowired
    CompanyStaffService companyStaffService;

	@RequestMapping(value = "/weiXinJump")
	public ModelAndView weiXinJump(HttpServletRequest request, HttpServletResponse response) {
		
		Map<String, String> map = RequestTools.requestParamToMap(request);
		String code = map.get("code");
		logger.info("shareOpenid value is : " + map.get("shareOpenid"));
		if(code == null) {
			throw new RuntimeException("回调地址没有带code！");
		}
		
		JSONObject stepOneJson = getOpenIdStepOne(code);
		UserInfo userInfo = null;
		//获取OpenId
		String openId = stepOneJson.getString("openid");
		map.put("openId", openId);
		logger.info("openId value is :" + openId);
		logger.info("openId access_token is :" + stepOneJson.getString("access_token"));
		//获取用户信息
		JSONObject jsonStepThree = this.getWxUserInfo(openId, stepOneJson.getString("access_token"));
		String nickname = jsonStepThree.getString("nickname");
		String headimgurl = jsonStepThree.getString("headimgurl");
		String sex = jsonStepThree.getString("sex");
		String shareOpenid =  map.get("shareOpenid");
		String activeId = map.get("activeId");

		//邀请好友处理逻辑  如果A分享给B   B点击     先查看B是否是已经注册
		isHaveOpenId(map, openId, shareOpenid);
		//原有的登录处理逻辑 //点击公众号菜单链接进来，如果有openid就更新  没有就添加用户信息
		userInfo = userService.wechatLogin(openId, nickname, headimgurl, sex, shareOpenid, activeId);

		if(userInfo.getId() == null) {
			logger.error("用户信息获取失败:");
		}
		Boolean isTeacher = isTeacher(map);
		//需要特殊处理的跳转逻辑
		delPath(map, userInfo);

		if(userInfo != null){
			this.setUserId(userInfo.getId());
			this.setUserInfo(userInfo);
		}
		
		return new ModelAndView("redirect:" + getUrlWithMap(map, isTeacher));
	}
	

	//不处理分享的逻辑  放到页面处理
	public void isHaveOpenId(Map<String, String> map, String openId, String shareOpenid) {
//		UserInfo userInfo = userService.getUserInfoByOpenId(openId);
//		if(userInfo != null && userInfo.getId() != null && StringUtils.isNotBlank(shareOpenid)) {
//			int isSubScribe = userService.isSubScribe(userInfo.getId().toString());//1已关注  0 为关注
//			String path = map.get("path");
//			if(path != null && path.contains("/share_new") && isSubScribe == 1){
//				map.put("path", "/home/invite_new");
//			}
//		}
	}

	//是否是教练
	public Boolean isTeacher(Map<String, String> map) {
		boolean isTeacher = false;
		//如果是教练  则需要判断教练是否绑定手机号码  
		if(map.get("path").equals("/phone_bind") || map.get("path").equals("/level_page/course/course_team")) {
			isTeacher = true;
		}
		return isTeacher;
	}

	public void delPath(Map<String, String> map, UserInfo userInfo) {
		if(map.get("path").equals("/home/vip_bind_index")) {
			boolean isBind = userService.judgeUserInfoIfPresellVip(userInfo);
			if(isBind) {
				map.put("path", "/home/open_vip");
			}
		}
		//如果是教练  则需要判断教练是否绑定手机号码
		logger.info("coach info return path value is  : " + map.get("path"));
		if(map.get("path").equals("/home/coach_phone_bind") || map.get("path").equals("/level_page/course/course_team")) {
			Map<String, Object> mapPWD = accessService.queryCoachPwdStatus(userInfo.getId());
			String type = mapPWD.get("type").toString();
			logger.info("coach info return type value is  : " + type);
			if("1".equals(type)) {//  密码有效  调到密码显示页面
				if(map.get("path").equals("/level_page/course/course_team")) {
					map.put("path", "/level_page/course/course_team");
				} else {
					map.put("pwdJson", JSON.toJSONString(mapPWD.get("pwd")));
					map.put("path", "/home/get_pwd");
				}
			} else if("2".equals(type)) { // 未请求密码 或密码已过期 跳转到请求密码界面
				if(map.get("path").equals("/level_page/course/course_team")) {
					map.put("path", "/level_page/course/course_team");
				} else {
					map.put("path", "/home/success");
				}
			} else if("3".equals(type)) { // 未绑定  跳绑定页面 /phone_bind
				if(map.get("path").equals("/level_page/course/course_team")) {
					map.put("fromPath", "/level_page/course/course_team");
				} 
				map.put("path", "/home/coach_phone_bind");
			}
		} else if(map.get("path").equals("/home/bind") || map.get("path").equals("/home/my_company")) {
			 boolean companyStaff = companyStaffService.isIfBindingCompany(map.get("openId"));
			 if(!companyStaff) {
				 map.put("path", "/home/bind");
			 } else {
				 map.put("path", "/home/my_company");
			 }
		}
	}
	
	/**
	 * 登录回调
	 * @param map
	 */
	public UserInfo commLogin(Map<String, String> map) {
		String code = map.get("code");
		if(code == null) {
			throw new RuntimeException("回调地址没有带code！");
		}
		JSONObject stepOneJson = getOpenIdStepOne(code);
		//获取OpenId
		String openId = stepOneJson.getString("openid");
		logger.info("openId value is :" + openId);
		logger.info("openId access_token is :" + stepOneJson.getString("access_token"));
		//获取用户信息
		JSONObject jsonStepThree = this.getWxUserInfo(openId, stepOneJson.getString("access_token"));
		String nickname = jsonStepThree.getString("nickname");
		String headimgurl = jsonStepThree.getString("headimgurl");
		String sex = jsonStepThree.getString("sex");
		String shareOpenid =  map.get("shareOpenid");
		String activeId = map.get("activeId");
		//原有的登录处理逻辑 //点击公众号菜单链接进来，如果有openid就更新  没有就添加用户信息
		UserInfo userInfo = userService.wechatLogin(openId, nickname, headimgurl, sex, shareOpenid, activeId);
		
		if(userInfo != null){
			this.setUserId(userInfo.getId());
			this.setUserInfo(userInfo);
		}
		return userInfo;
	}
	
	/**
	 * 签到回调
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/singIn")
    public ModelAndView signIn(HttpServletRequest request) {
		Map<String, String> map = RequestTools.requestParamToMap(request);
		UserInfo userInfo = commLogin(map);
		String courseIdTemp = map.get("courseId");
		if(StringUtils.isNotBlank(courseIdTemp)) {
			Integer courseId = Integer.parseInt(courseIdTemp);
			try {
				ApiResultModel isSign = courseSignService.courseCoachUserSign(courseId, userInfo.getOpenid());
				Map<String, Object> isSignMap = (Map<String, Object>) isSign.getData();
				//签到是否成功  签到如果没有成功   msg就会有错误信息 否则为null
				for(Map.Entry<String, Object> entry:isSignMap.entrySet()){    
				     System.out.println(entry.getKey()+"--->"+entry.getValue()); 
				     map.put(entry.getKey(), StringUtils.isBlank(entry.getValue().toString()) ? null : strToUTF8(entry.getValue().toString()));
				}
				map.put("isSign", Boolean.parseBoolean(isSignMap.get("success").toString()) ? "true" : "false");
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("签到失败！！" + e.toString() + e.getCause(),e);
			}
		}
		logger.info("openId value is :" +  userInfo.getOpenid());
		return new ModelAndView("redirect:" + getUrlWithMap(map, false));
    }

	public String strToUTF8(String str) {
		try{  
		    str = java.net.URLEncoder.encode(str,"UTF-8");  
		}catch(Exception ex){
		    ex.printStackTrace();
			logger.error(ex.toString() + ex.getCause(),ex);
		}  
		return str;
	}
    /**
     * 第二步 获取openID  和reflashToken
     * @return
     */
    public JSONObject getOpenIdStepOne(String code) {
    	Map<String, String> map = new HashMap<String, String>();
        map.put("appid", APP_ID);
        map.put("secret", APP_SECRET);   
        map.put("code", code);
        map.put("grant_type", GRANT_TYPE);
        logger.info("get open Id param is : ");
        logger.info("get open Id value is : " + map);
        
        JSONObject json = JsonClient.post(GET_ACCESS_TOKEN, map);
        if(json.containsKey("errcode")){
        	throw new RuntimeException("根据code获取用户OpenId失败 errcode:" + json.getString("errcode"));
        }
    	return json;
    }
    
    /**
     * 第三步  刷新flashToken
     * @return
     */
    public JSONObject refleshData(String refresh_token) {
    	Map<String, String> map = new HashMap<String, String>();
        map.put("appid", APP_ID);
        map.put("grant_type", "refresh_token");   
        map.put("refresh_token", refresh_token);
        JSONObject json = JsonClient.post(REFLASH_DATA, map);
        if(json.containsKey("errcode")){
       		logger.error("根据第三步的reflash_code 刷新失败 errcode:" + json.getString("errcode"));
        }
    	return json;
    }
    
    /**
     * 第四步获取用户基础信息
     * @return
     */
    public JSONObject getWxUserInfo(String openid, String access_token) {
    	Map<String, String> map = new HashMap<String, String>();
        map.put("openid", openid);
        map.put("access_token", access_token);   
        map.put("lang", LANG);
        JSONObject json = JsonClient.post(GET_USER_INFO, map);
        if(json.containsKey("errcode")){
       		logger.error(openid + "根据第四步的获取用户信息失败 errcode:" + json.getString("errcode"));
        }
    	return json;
    }
    
    //判断是否是自己点击自己分享出去的链接
    private void isSelfClick(Map<String, String> map) {
    	String isSelf = "false";
    	String openId = map.get("openId");
    	String shareOpenid = map.get("shareOpenid");
    	if(StringUtil.notNull(openId) && StringUtil.notNull(shareOpenid)) {
    		try {
    			DesUtils des = new DesUtils(String.valueOf(PropertiesUtil.get("des_key")).trim());
				shareOpenid =  des.decrypt(shareOpenid);
			} catch (Exception e) {
				logger.error("openid 解密失败" + e.getMessage());
			}
    		if(openId.equals(shareOpenid)) {
    			isSelf = "true";
    		}
		}
    	map.put("isSelf", isSelf);
    }
    /**
     * 获取传过来的参数拼接返回的参数
     * @return
     * @throws UnsupportedEncodingException 
     */
    public String getUrlWithMap(Map<String, String> map, Boolean isTeacher)  {
    	logger.info("weixin  Jump start :" + map);
		String paramsWithUri = "?";
		Set<String> set = map.keySet();
		//判断谁点击了链接
		isSelfClick(map);
		
		String nickname = null;
		for (String arg : set) {
			if (arg.equals("path") || arg.equals("openId") || arg.equals("code") || arg.equals("state") || arg.equals("isSelf")) {
				continue;
			}
			if(arg.equals("nickname")) {
				try {
					nickname = URLEncoder.encode(map.get(arg),"utf-8");
					paramsWithUri += "&" + arg + "=" + nickname;
					logger.info(arg + " pathUrl value is : >" + map.get(arg));
					continue;
				} catch (UnsupportedEncodingException e) {
				    e.printStackTrace();
					logger.debug(e.toString() + e.getCause());
				}
			}
			logger.info(arg + " pathUrl value is : >" + map.get(arg));
			paramsWithUri += "&" + arg + "=" + map.get(arg);
		}
		
		Long timeStr = System.currentTimeMillis();
		paramsWithUri += "&_=" + timeStr; 
		paramsWithUri = paramsWithUri.replaceFirst("&", "");
		logger.info("pathUrl paramsWithUri is : " + paramsWithUri);
		Boolean isHaveParam = map.get("path") != null & map.get("path").indexOf("?") > 0 ? true : false;
		logger.info("pathUrl isHaveParam is : " + TEACHER_URL);
		String pathUrl = isTeacher ? TEACHER_URL : BASE_URL;
		pathUrl += map.get("path");
		pathUrl += isHaveParam ? paramsWithUri.replaceFirst("\\?", "&") : paramsWithUri;
		logger.info("weixin  Jump end  pathUrl  is : " + pathUrl);
		return pathUrl;
    }
    
    /**
     * 判断该用户是否是新用户
     * 判断逻辑：
     * 该用户未在公众平台有过购买消费记录
     * 并且该用户未领取过activityId该活动的优惠券
     * @return
     */
    @ResponseBody
    @RequestMapping("/user_or_coupon_exists")
    public String UserExistsAndIsHaveCoupon(HttpServletRequest request,HttpServletResponse response){
    	ApiResultModel<Object> apiResultModel = new ApiResultModel<>();
    	Integer activityId = RequestTools.RequestInt(request, "activityId", 0);
    	String callback= RequestTools.RequestString(request, "callback", "");
    	String shareOpenid = RequestTools.RequestString(request, "shareOpenid", "");
    	logger.info("step 1 :" + this.isLogined());
    	if(!this.isLogined()) {
    		apiResultModel.setLogined(this.isLogined());
    		apiResultModel.setMsg("用户未登陆");
    		apiResultModel.setRet(ApiResultModel.RET_ERROR);
    		logger.info("step 2 :" + this.isLogined());
    		return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel),callback);
    	}
    	String openId = this.getUserInfo().getOpenid();
    	if(StringUtils.isEmpty(openId)){
    		apiResultModel.setRet(ApiResultModel.RET_ERROR);
    		apiResultModel.setLogined(this.isLogined());
    		apiResultModel.setMsg("openId为null！");
    		logger.info("step 3 :" + this.isLogined());
    		return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel),callback);
    	}
    	if(activityId < 1){
    		apiResultModel.setRet(ApiResultModel.RET_ERROR);
    		apiResultModel.setLogined(this.isLogined());
    		apiResultModel.setMsg("活动不存在！");
    		return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel),callback);
    	}
    	try {
    		UserInfo shareUserInfo = null;
    		if(StringUtil.notNull(shareOpenid)) {
				try {
					DesUtils des = new DesUtils(String.valueOf(PropertiesUtil.get("des_key")).trim());
					shareOpenid =  des.decrypt(shareOpenid);
				} catch (Exception e) {
					logger.info(e.getMessage());
				}
				shareUserInfo = userService.getUserInfoByOpenId(shareOpenid);
			} else {
    			apiResultModel.setRet(ApiResultModel.RET_ERROR);
        		apiResultModel.setLogined(this.isLogined());
        		apiResultModel.setMsg("邀请链接失效！");
        		return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel),callback);
    		}
    		Map<String,Object> map = userService.isNewCustomOrInsert(openId, this.getUserInfo(), activityId, shareUserInfo);
    		map.put("userInfo", this.getUserInfo());
    		apiResultModel.setData(map);
    		apiResultModel.setRet(ApiResultModel.RET_SUCCESS);
    		apiResultModel.setMsg("成功!");
    		logger.info("step 4 :" + this.isLogined());
    		apiResultModel.setLogined(this.isLogined());
    		
		} catch (Exception e) {
			apiResultModel.setRet(ApiResultModel.RET_ERROR);
    		apiResultModel.setMsg("系统运行异常！");
		}
    	return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel),callback);
    }
    
    /**
     * 根据用户的opedId和activityId获取临时二维码
     * @param request
     * @param response
     * @return
     */
    @ResponseBody
    @RequestMapping("/wechat_qrscene")
    public String weChatQRSceneImgUrl(HttpServletRequest request,HttpServletResponse response){
		ApiResultModel<Object> apiResultModel = new ApiResultModel<Object>();
		String callback = RequestTools.RequestString(request, "callback", "");
		String openId = RequestTools.RequestString(request, "openId", null);
		Integer activityId = RequestTools.RequestInt(request, "activityId", 0);
		Integer userId = RequestTools.RequestInt(request, "userId", 0);
		
		try {
			UserInfo userInfo = userService.getUserInfoByOpenId(openId);
			if(userInfo != null){
				apiResultModel.setData(userService.getQRSceneImgUrl(userId, activityId));
				apiResultModel.setRet(apiResultModel.RET_SUCCESS);
			}else{
				apiResultModel.setRet(apiResultModel.RET_ERROR);
				apiResultModel.setMsg("用户不存在录！");
				return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel), callback);
			}
		} catch (Exception e) {
			// TODO: handle exception
			apiResultModel.setRet(apiResultModel.RET_ERROR);
			apiResultModel.setMsg("系统运行异常！");

		}
		return ResponseTools.CallBackResultJsonP(JsonTools.jsonSer(apiResultModel), callback);
    }
    
}
